// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include "base/files/file_path.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/quic/crypto/proof_source.h"
#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"

using std::string;
using std::vector;

namespace net {
namespace test {
    namespace {

        // TestProofVerifierCallback is a simple callback for a ProofVerifier that
        // signals a TestCompletionCallback when called and stores the results from the
        // ProofVerifier in pointers passed to the constructor.
        class TestProofVerifierCallback : public ProofVerifierCallback {
        public:
            TestProofVerifierCallback(TestCompletionCallback* comp_callback,
                bool* ok,
                string* error_details)
                : comp_callback_(comp_callback)
                , ok_(ok)
                , error_details_(error_details)
            {
            }

            void Run(bool ok,
                const string& error_details,
                std::unique_ptr<ProofVerifyDetails>* details) override
            {
                *ok_ = ok;
                *error_details_ = error_details;

                comp_callback_->callback().Run(0);
            }

        private:
            TestCompletionCallback* const comp_callback_;
            bool* const ok_;
            string* const error_details_;
        };

        // RunVerification runs |verifier->VerifyProof| and asserts that the result
        // matches |expected_ok|.
        void RunVerification(ProofVerifier* verifier,
            const string& hostname,
            const uint16_t port,
            const string& server_config,
            QuicVersion quic_version,
            StringPiece chlo_hash,
            const vector<string>& certs,
            const string& proof,
            bool expected_ok)
        {
            std::unique_ptr<ProofVerifyDetails> details;
            TestCompletionCallback comp_callback;
            bool ok;
            string error_details;
            std::unique_ptr<ProofVerifyContext> verify_context(
                CryptoTestUtils::ProofVerifyContextForTesting());
            TestProofVerifierCallback* callback = new TestProofVerifierCallback(&comp_callback, &ok, &error_details);

            QuicAsyncStatus status = verifier->VerifyProof(
                hostname, port, server_config, quic_version, chlo_hash, certs, "", proof,
                verify_context.get(), &error_details, &details, callback);

            switch (status) {
            case QUIC_FAILURE:
                delete callback;
                ASSERT_FALSE(expected_ok);
                ASSERT_NE("", error_details);
                return;
            case QUIC_SUCCESS:
                delete callback;
                ASSERT_TRUE(expected_ok);
                ASSERT_EQ("", error_details);
                return;
            case QUIC_PENDING:
                comp_callback.WaitForResult();
                ASSERT_EQ(expected_ok, ok);
                break;
            }
        }

        // Reads the certificate named "quic_" + |file_name| in the test data directory.
        // The certificate must be PEM encoded. Returns the DER-encoded certificate.
        string LoadTestCert(const string& file_name)
        {
            base::FilePath certs_dir = GetTestCertsDirectory();
            scoped_refptr<X509Certificate> cert = ImportCertFromFile(certs_dir, "quic_" + file_name);
            CHECK_NE(static_cast<X509Certificate*>(nullptr), cert.get());

            string der_bytes;
            CHECK(X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_bytes));
            return der_bytes;
        }

        class ProofTest : public ::testing::TestWithParam<QuicVersion> {
        };

    } // namespace

    INSTANTIATE_TEST_CASE_P(QuicVersion,
        ProofTest,
        ::testing::ValuesIn(QuicSupportedVersions()));

    // TODO(rtenneti): Enable testing of ProofVerifier. See http://crbug.com/514468.
    TEST_P(ProofTest, DISABLED_Verify)
    {
        std::unique_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
        std::unique_ptr<ProofVerifier> verifier(
            CryptoTestUtils::ProofVerifierForTesting());

        const string server_config = "server config bytes";
        const string hostname = "test.example.com";
        const uint16_t port = 8443;
        const string first_chlo_hash = "first chlo hash bytes";
        const string second_chlo_hash = "first chlo hash bytes";
        const QuicVersion quic_version = GetParam();

        scoped_refptr<ProofSource::Chain> chain;
        scoped_refptr<ProofSource::Chain> first_chain;
        string error_details, signature, first_signature, first_cert_sct, cert_sct;
        IPAddress server_ip;

        ASSERT_TRUE(source->GetProof(
            server_ip, hostname, server_config, quic_version, first_chlo_hash,
            false /* no ECDSA */, &first_chain, &first_signature, &first_cert_sct));
        ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version,
            second_chlo_hash, false /* no ECDSA */, &chain,
            &signature, &cert_sct));

        // Check that the proof source is caching correctly:
        ASSERT_EQ(first_chain->certs, chain->certs);
        if (GetParam() < QUIC_VERSION_31) {
            ASSERT_EQ(signature, first_signature);
        } else {
            // QUIC 31 includes the CHLO hash.
            ASSERT_NE(signature, first_signature);
        }
        ASSERT_EQ(first_cert_sct, cert_sct);

        RunVerification(verifier.get(), hostname, port, server_config, quic_version,
            first_chlo_hash, chain->certs, signature, true);

        RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
            first_chlo_hash, chain->certs, signature, false);

        RunVerification(verifier.get(), server_config.substr(1, string::npos), port,
            server_config, quic_version, first_chlo_hash, chain->certs,
            signature, false);

        const string corrupt_signature = "1" + signature;
        RunVerification(verifier.get(), hostname, port, server_config, quic_version,
            first_chlo_hash, chain->certs, corrupt_signature, false);

        vector<string> wrong_certs;
        for (size_t i = 1; i < chain->certs.size(); i++) {
            wrong_certs.push_back(chain->certs[i]);
        }

        RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
            first_chlo_hash, wrong_certs, corrupt_signature, false);
    }

    TEST_P(ProofTest, UseAfterFree)
    {
        ProofSource* source = CryptoTestUtils::ProofSourceForTesting();

        const string server_config = "server config bytes";
        const string hostname = "test.example.com";
        const string chlo_hash = "proof nonce bytes";
        scoped_refptr<ProofSource::Chain> chain;
        string error_details, signature, cert_sct;
        IPAddress server_ip;

        ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, GetParam(),
            chlo_hash, false /* no ECDSA */, &chain,
            &signature, &cert_sct));

        // Make sure we can safely access results after deleting where they came from.
        EXPECT_FALSE(chain->HasOneRef());
        delete source;
        EXPECT_TRUE(chain->HasOneRef());

        EXPECT_FALSE(chain->certs.empty());
        for (const string& cert : chain->certs) {
            EXPECT_FALSE(cert.empty());
        }
    }

    // A known answer test that allows us to test ProofVerifier without a working
    // ProofSource.
    TEST_P(ProofTest, VerifyRSAKnownAnswerTest)
    {
        if (GetParam() > QUIC_VERSION_30) {
            return;
        }
        // These sample signatures were generated by running the Proof.Verify test
        // and dumping the bytes of the |signature| output of ProofSource::GetProof().
        static const unsigned char signature_data_0[] = {
            0x31,
            0xd5,
            0xfb,
            0x40,
            0x30,
            0x75,
            0xd2,
            0x7d,
            0x61,
            0xf9,
            0xd7,
            0x54,
            0x30,
            0x06,
            0xaf,
            0x54,
            0x0d,
            0xb0,
            0x0a,
            0xda,
            0x63,
            0xca,
            0x7e,
            0x9e,
            0xce,
            0xba,
            0x10,
            0x05,
            0x1b,
            0xa6,
            0x7f,
            0xef,
            0x2b,
            0xa3,
            0xff,
            0x3c,
            0xbb,
            0x9a,
            0xe4,
            0xbf,
            0xb8,
            0x0c,
            0xc1,
            0xbd,
            0xed,
            0xc2,
            0x90,
            0x68,
            0xeb,
            0x45,
            0x48,
            0xea,
            0x3c,
            0x95,
            0xf8,
            0xa2,
            0xb9,
            0xe7,
            0x62,
            0x29,
            0x00,
            0xc3,
            0x18,
            0xb4,
            0x16,
            0x6f,
            0x5e,
            0xb0,
            0xc1,
            0x26,
            0xc0,
            0x4b,
            0x84,
            0xf5,
            0x97,
            0xfc,
            0x17,
            0xf9,
            0x1c,
            0x43,
            0xb8,
            0xf2,
            0x3f,
            0x38,
            0x32,
            0xad,
            0x36,
            0x52,
            0x2c,
            0x26,
            0x92,
            0x7a,
            0xea,
            0x2c,
            0xa2,
            0xf4,
            0x28,
            0x2f,
            0x19,
            0x4d,
            0x1f,
            0x11,
            0x46,
            0x82,
            0xd0,
            0xc4,
            0x86,
            0x56,
            0x5c,
            0x97,
            0x9e,
            0xc6,
            0x37,
            0x8e,
            0xaf,
            0x9d,
            0x69,
            0xe9,
            0x4f,
            0x5a,
            0x6d,
            0x70,
            0x75,
            0xc7,
            0x41,
            0x95,
            0x68,
            0x53,
            0x94,
            0xca,
            0x31,
            0x63,
            0x61,
            0x9f,
            0xb8,
            0x8c,
            0x3b,
            0x75,
            0x36,
            0x8b,
            0x69,
            0xa2,
            0x35,
            0xc0,
            0x4b,
            0x77,
            0x55,
            0x08,
            0xc2,
            0xb4,
            0x56,
            0xd2,
            0x81,
            0xce,
            0x9e,
            0x25,
            0xdb,
            0x50,
            0x74,
            0xb3,
            0x8a,
            0xd9,
            0x20,
            0x42,
            0x3f,
            0x85,
            0x2d,
            0xaa,
            0xfd,
            0x66,
            0xfa,
            0xd6,
            0x95,
            0x55,
            0x6b,
            0x63,
            0x63,
            0x04,
            0xf8,
            0x6c,
            0x3e,
            0x08,
            0x22,
            0x39,
            0xb9,
            0x9a,
            0xe0,
            0xd7,
            0x01,
            0xff,
            0xeb,
            0x8a,
            0xb9,
            0xe2,
            0x34,
            0xa5,
            0xa0,
            0x51,
            0xe9,
            0xbe,
            0x15,
            0x12,
            0xbf,
            0xbe,
            0x64,
            0x3d,
            0x3f,
            0x98,
            0xce,
            0xc1,
            0xa6,
            0x33,
            0x32,
            0xd3,
            0x5c,
            0xa8,
            0x39,
            0x93,
            0xdc,
            0x1c,
            0xb9,
            0xab,
            0x3c,
            0x80,
            0x62,
            0xb3,
            0x76,
            0x21,
            0xdf,
            0x47,
            0x1e,
            0xa9,
            0x0e,
            0x5e,
            0x8a,
            0xbe,
            0x66,
            0x5b,
            0x7c,
            0x21,
            0xfa,
            0x78,
            0x2d,
            0xd1,
            0x1d,
            0x5c,
            0x35,
            0x8a,
            0x34,
            0xb2,
            0x1a,
            0xc2,
            0xc4,
            0x4b,
            0x53,
            0x54,
        };
        static const unsigned char signature_data_1[] = {
            0x01,
            0x7b,
            0x52,
            0x35,
            0xe3,
            0x51,
            0xdd,
            0xf1,
            0x67,
            0x8d,
            0x31,
            0x5e,
            0xa3,
            0x75,
            0x1f,
            0x68,
            0x6c,
            0xdd,
            0x41,
            0x7a,
            0x18,
            0x25,
            0xe0,
            0x12,
            0x6e,
            0x84,
            0x46,
            0x5e,
            0xb2,
            0x98,
            0xd7,
            0x84,
            0xe1,
            0x62,
            0xe0,
            0xc1,
            0xc4,
            0xd7,
            0x4f,
            0x4f,
            0x80,
            0xc1,
            0x92,
            0xd6,
            0x02,
            0xaf,
            0xca,
            0x28,
            0x9f,
            0xe0,
            0xf3,
            0x74,
            0xd7,
            0xf1,
            0x44,
            0x67,
            0x59,
            0x27,
            0xc8,
            0xc2,
            0x8b,
            0xd4,
            0xe5,
            0x4a,
            0x07,
            0xfd,
            0x00,
            0xd6,
            0x8a,
            0xbf,
            0x8b,
            0xcd,
            0x6a,
            0xe0,
            0x1d,
            0xf6,
            0x4b,
            0x68,
            0x0f,
            0xcf,
            0xb9,
            0xd0,
            0xa1,
            0xbc,
            0x2e,
            0xcf,
            0x7c,
            0x03,
            0x47,
            0x11,
            0xe4,
            0x4c,
            0xbc,
            0x1b,
            0x6b,
            0xa5,
            0x2a,
            0x82,
            0x86,
            0xa4,
            0x7f,
            0x1d,
            0x85,
            0x64,
            0x21,
            0x10,
            0xd2,
            0xb2,
            0xa0,
            0x31,
            0xa2,
            0x78,
            0xe6,
            0xf2,
            0xea,
            0x96,
            0x38,
            0x8c,
            0x9a,
            0xe1,
            0x01,
            0xab,
            0x8e,
            0x95,
            0x66,
            0xc8,
            0xe5,
            0xcc,
            0x80,
            0xa3,
            0xbd,
            0x16,
            0xa7,
            0x79,
            0x19,
            0x39,
            0x61,
            0x3d,
            0xff,
            0x37,
            0xca,
            0x9f,
            0x97,
            0x05,
            0xc7,
            0xcb,
            0xf0,
            0xea,
            0xaf,
            0x64,
            0x07,
            0xc0,
            0xed,
            0x2a,
            0x98,
            0xa4,
            0xaf,
            0x04,
            0x6f,
            0xf2,
            0xc9,
            0xb2,
            0x73,
            0x9a,
            0x56,
            0x85,
            0x43,
            0x64,
            0x5f,
            0xaa,
            0xb7,
            0xff,
            0x31,
            0x4c,
            0x2e,
            0x6c,
            0x17,
            0xcf,
            0xe5,
            0xbe,
            0x7f,
            0x7e,
            0xad,
            0xf5,
            0x6f,
            0x84,
            0x50,
            0x20,
            0x29,
            0xb3,
            0x57,
            0xe7,
            0xb1,
            0xdc,
            0x2c,
            0x95,
            0x48,
            0xfe,
            0xb0,
            0xc1,
            0x92,
            0xda,
            0xc5,
            0x58,
            0x95,
            0xb0,
            0x1a,
            0x3a,
            0x05,
            0x71,
            0x3c,
            0x6d,
            0x20,
            0x01,
            0x4c,
            0xa9,
            0xe4,
            0x38,
            0x08,
            0x65,
            0xb4,
            0xbd,
            0x86,
            0x76,
            0xbd,
            0xad,
            0x25,
            0x06,
            0x74,
            0x0b,
            0xca,
            0x95,
            0x27,
            0x0c,
            0x13,
            0x08,
            0x7e,
            0x30,
            0xcf,
            0xf6,
            0xb5,
            0xc1,
            0x2a,
            0x08,
            0xfc,
            0x4b,
            0xc6,
            0xb5,
            0x2f,
            0x23,
            0x27,
            0x32,
            0x89,
            0xdb,
            0x0e,
            0x4a,
        };
        static const unsigned char signature_data_2[] = {
            0x6d,
            0x7d,
            0x22,
            0x8c,
            0x85,
            0xc4,
            0x8a,
            0x80,
            0x05,
            0xe4,
            0x3c,
            0xaf,
            0x10,
            0x3b,
            0xe3,
            0x51,
            0xb1,
            0x86,
            0x52,
            0x63,
            0xb6,
            0x17,
            0x33,
            0xbd,
            0x1b,
            0x1e,
            0xc4,
            0x50,
            0x10,
            0xfc,
            0xcc,
            0xea,
            0x6b,
            0x11,
            0xeb,
            0x6d,
            0x5e,
            0x00,
            0xe7,
            0xf3,
            0x67,
            0x99,
            0x74,
            0x53,
            0x12,
            0x8f,
            0xe4,
            0x3e,
            0x20,
            0x17,
            0x8e,
            0x83,
            0xe6,
            0xdc,
            0x83,
            0x91,
            0x0e,
            0xf3,
            0x69,
            0x22,
            0x95,
            0x14,
            0xdf,
            0xc1,
            0xda,
            0xb5,
            0xdb,
            0x6a,
            0x1a,
            0xb4,
            0x4f,
            0x26,
            0xd0,
            0x32,
            0x1d,
            0x73,
            0x95,
            0x1f,
            0x39,
            0x1d,
            0x00,
            0xcb,
            0xc3,
            0x92,
            0x49,
            0x53,
            0xcb,
            0x5c,
            0x36,
            0x70,
            0x19,
            0xd9,
            0x64,
            0x36,
            0xda,
            0xfb,
            0x20,
            0xe5,
            0x47,
            0xd9,
            0x08,
            0xc6,
            0x5a,
            0x9e,
            0x87,
            0x1a,
            0xdb,
            0x11,
            0x7b,
            0x17,
            0xfc,
            0x53,
            0x7b,
            0xc1,
            0xa0,
            0xc0,
            0x33,
            0xcf,
            0x96,
            0xba,
            0x03,
            0x79,
            0x8e,
            0xc6,
            0x05,
            0xd2,
            0xb7,
            0xa2,
            0xe2,
            0xc1,
            0x67,
            0xb7,
            0x6a,
            0xeb,
            0xb1,
            0x40,
            0xbb,
            0x7d,
            0x57,
            0xcb,
            0xc2,
            0x60,
            0x9f,
            0xf1,
            0x72,
            0xe5,
            0xad,
            0xce,
            0x95,
            0x45,
            0x7c,
            0xbc,
            0x75,
            0x81,
            0x45,
            0x19,
            0xe1,
            0xa7,
            0x2f,
            0x05,
            0x52,
            0xeb,
            0xed,
            0xdd,
            0x19,
            0xd9,
            0x1a,
            0xc9,
            0x5a,
            0x06,
            0x8e,
            0x29,
            0x54,
            0xb5,
            0x4f,
            0x80,
            0xaa,
            0x36,
            0x36,
            0xc0,
            0xff,
            0x64,
            0xac,
            0xe8,
            0x0f,
            0x99,
            0x35,
            0x5e,
            0xc6,
            0x72,
            0x1f,
            0x8c,
            0xc4,
            0x2b,
            0x7d,
            0xc1,
            0xfb,
            0xf0,
            0x12,
            0x61,
            0xb1,
            0x18,
            0x65,
            0xdd,
            0xc2,
            0x38,
            0x92,
            0xba,
            0x84,
            0xf8,
            0xc8,
            0x5e,
            0x17,
            0x63,
            0xe0,
            0x9c,
            0x2c,
            0xe6,
            0x70,
            0x71,
            0xdc,
            0xe5,
            0xc1,
            0xea,
            0xb3,
            0x9a,
            0xb6,
            0x91,
            0xdc,
            0xc5,
            0x56,
            0x84,
            0x8a,
            0x31,
            0x31,
            0x23,
            0x61,
            0x94,
            0x7e,
            0x01,
            0x22,
            0x49,
            0xf3,
            0xcb,
            0x0e,
            0x31,
            0x03,
            0x04,
            0x1b,
            0x14,
            0x43,
            0x7c,
            0xad,
            0x42,
            0xe5,
            0x55,
        };

        std::unique_ptr<ProofVerifier> verifier(
            CryptoTestUtils::RealProofVerifierForTesting());

        const string server_config = "server config bytes";
        const string hostname = "test.example.com";
        const uint16_t port = 8443;
        const string chlo_hash = "proof nonce bytes";
        const QuicVersion quic_version = GetParam();

        vector<string> certs(2);
        certs[0] = LoadTestCert("test.example.com.crt");
        certs[1] = LoadTestCert("intermediate.crt");

        // Signatures are nondeterministic, so we test multiple signatures on the
        // same server_config.
        vector<string> signatures(3);
        signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
            sizeof(signature_data_0));
        signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
            sizeof(signature_data_1));
        signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
            sizeof(signature_data_2));

        for (size_t i = 0; i < signatures.size(); i++) {
            const string& signature = signatures[i];

            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, certs, signature, true);
            RunVerification(verifier.get(), "foo.com", port, server_config,
                quic_version, chlo_hash, certs, signature, false);
            RunVerification(verifier.get(), hostname, port,
                server_config.substr(1, string::npos), quic_version,
                chlo_hash, certs, signature, false);

            const string corrupt_signature = "1" + signature;
            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, certs, corrupt_signature, false);

            vector<string> wrong_certs;
            for (size_t i = 1; i < certs.size(); i++) {
                wrong_certs.push_back(certs[i]);
            }
            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, wrong_certs, signature, false);
        }
    }

    // A known answer test that allows us to test ProofVerifier without a working
    // ProofSource.
    TEST_P(ProofTest, VerifyECDSAKnownAnswerTest)
    {
        if (GetParam() > QUIC_VERSION_30) {
            return;
        }

        // These sample signatures were generated by running the Proof.Verify test
        // (modified to use ECDSA for signing proofs) and dumping the bytes of the
        // |signature| output of ProofSource::GetProof().
        static const unsigned char signature_data_0[] = {
            0x30,
            0x45,
            0x02,
            0x21,
            0x00,
            0x89,
            0xc4,
            0x7d,
            0x08,
            0xd1,
            0x49,
            0x19,
            0x6c,
            0xd1,
            0x7c,
            0xb9,
            0x25,
            0xe0,
            0xe3,
            0xbd,
            0x6a,
            0x5c,
            0xd7,
            0xaa,
            0x0c,
            0xdc,
            0x4f,
            0x8e,
            0xeb,
            0xde,
            0xbf,
            0x32,
            0xf8,
            0xd1,
            0x84,
            0x95,
            0x97,
            0x02,
            0x20,
            0x29,
            0x3d,
            0x49,
            0x22,
            0x73,
            0xed,
            0x8b,
            0xde,
            0x3d,
            0xc2,
            0xa4,
            0x20,
            0xcc,
            0xe7,
            0xc8,
            0x2a,
            0x85,
            0x20,
            0x9b,
            0x5b,
            0xda,
            0xcd,
            0x58,
            0x23,
            0xbe,
            0x89,
            0x73,
            0x31,
            0x87,
            0x51,
            0xd1,
            0x01,
        };
        static const unsigned char signature_data_1[] = {
            0x30,
            0x46,
            0x02,
            0x21,
            0x00,
            0xec,
            0xdf,
            0x69,
            0xc8,
            0x24,
            0x59,
            0x93,
            0xda,
            0x49,
            0xee,
            0x37,
            0x28,
            0xaf,
            0xeb,
            0x0e,
            0x2f,
            0x80,
            0x17,
            0x4b,
            0x3b,
            0xf6,
            0x54,
            0xcd,
            0x3b,
            0x86,
            0xc5,
            0x98,
            0x0d,
            0xff,
            0xc6,
            0xb1,
            0xe7,
            0x02,
            0x21,
            0x00,
            0xe1,
            0x36,
            0x8c,
            0xc0,
            0xf4,
            0x50,
            0x5f,
            0xba,
            0xfb,
            0xe2,
            0xff,
            0x1d,
            0x5d,
            0x64,
            0xe4,
            0x07,
            0xbb,
            0x5a,
            0x4b,
            0x19,
            0xb6,
            0x39,
            0x7a,
            0xc4,
            0x12,
            0xc6,
            0xe5,
            0x42,
            0xc8,
            0x78,
            0x33,
            0xcd,
        };
        static const unsigned char signature_data_2[] = {
            0x30,
            0x45,
            0x02,
            0x20,
            0x09,
            0x51,
            0xe9,
            0xde,
            0xdb,
            0x01,
            0xfd,
            0xb4,
            0xd8,
            0x20,
            0xbb,
            0xad,
            0x41,
            0xe3,
            0xaa,
            0xe7,
            0xa3,
            0xc3,
            0x32,
            0x10,
            0x9d,
            0xfa,
            0x37,
            0xce,
            0x17,
            0xd1,
            0x29,
            0xf9,
            0xd4,
            0x1d,
            0x0d,
            0x19,
            0x02,
            0x21,
            0x00,
            0xc6,
            0x20,
            0xd4,
            0x28,
            0xf9,
            0x70,
            0xb5,
            0xb4,
            0xff,
            0x4a,
            0x35,
            0xba,
            0xa0,
            0xf2,
            0x8e,
            0x00,
            0xf7,
            0xcb,
            0x43,
            0xaf,
            0x2d,
            0x1f,
            0xce,
            0x92,
            0x05,
            0xca,
            0x29,
            0xfe,
            0xd2,
            0x8f,
            0xd9,
            0x31,
        };

        std::unique_ptr<ProofVerifier> verifier(
            CryptoTestUtils::RealProofVerifierForTesting());

        const string server_config = "server config bytes";
        const string hostname = "test.example.com";
        const uint16_t port = 8443;
        const string chlo_hash = "chlo_hash nonce bytes";
        const QuicVersion quic_version = GetParam();

        vector<string> certs(2);
        certs[0] = LoadTestCert("test_ecc.example.com.crt");
        certs[1] = LoadTestCert("intermediate.crt");

        // Signatures are nondeterministic, so we test multiple signatures on the
        // same server_config.
        vector<string> signatures(3);
        signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
            sizeof(signature_data_0));
        signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
            sizeof(signature_data_1));
        signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
            sizeof(signature_data_2));

        for (size_t i = 0; i < signatures.size(); i++) {
            const string& signature = signatures[i];

            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, certs, signature, true);
            RunVerification(verifier.get(), "foo.com", port, server_config,
                quic_version, chlo_hash, certs, signature, false);
            RunVerification(verifier.get(), hostname, port,
                server_config.substr(1, string::npos), quic_version,
                chlo_hash, certs, signature, false);

            // An ECDSA signature is DER-encoded. Corrupt the last byte so that the
            // signature can still be DER-decoded correctly.
            string corrupt_signature = signature;
            corrupt_signature[corrupt_signature.size() - 1] += 1;
            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, certs, corrupt_signature, false);

            // Prepending a "1" makes the DER invalid.
            const string bad_der_signature1 = "1" + signature;
            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, certs, bad_der_signature1, false);

            vector<string> wrong_certs;
            for (size_t i = 1; i < certs.size(); i++) {
                wrong_certs.push_back(certs[i]);
            }
            RunVerification(verifier.get(), hostname, port, server_config, quic_version,
                chlo_hash, wrong_certs, signature, false);
        }
    }

} // namespace test
} // namespace net
